import { Vector as VectorLayer } from "ol/layer"
import { Vector as VectorSource } from "ol/source"
import { Fill, Stroke, Style, Text, Icon, Circle } from "ol/style"
import Feature from "ol/Feature"
import Point from "ol/geom/Point"
import LineString from "ol/geom/LineString"
import { GeoJSON, WFS, WKT } from "ol/format"
import { Image as ImageLayer, Tile as TileLayer } from "ol/layer"
import ImageWMS from "ol/source/ImageWMS"
import { toLonLat, fromLonLat, transform } from "ol/proj"
import Overlay from "ol/Overlay"
import { getVectorContext } from "ol/render"

import spng from "@/assets/images/start.png"
import epng from "@/assets/images/end.png"
import shippng from "@/assets/images/ship.png"
import h2 from "@/assets/images/h2.png"
import h3 from "@/assets/images/h3.png"
import hospng from "@/assets/images/hospotial.png"

class Routing {
  constructor(map) {
    this.map = map
    this.clickType = null
    this.eventFlag = false
    this.startPoint = null
    this.endPoint = null
    this.pointLayer = null
    this.routerLayer = null
    this.poiLayer = null
    this.islandsArr = []
    this.overLay = null
    this.animating = false
    this.distance = 0
    this.lastTime = 0
    this.position = null
    this.geoMarker = null
    this.islandPoints = []
    this.tempCoors = []
    this.jtgj = 1

    this.styles = {
      route: new Style({
        stroke: new Stroke({
          width: 6,
          color: [237, 212, 0, 0.8],
        }),
      }),
      icon: new Style({
        image: new Icon({
          anchor: [0.5, 1],
          scale: 0.8,
          src: spng,
        }),
      }),
      icon_plane: new Style({
        image: new Icon({
          // anchor: [0.5, 1],
          scale: 0.8,
          src: shippng,
        }),
      }),
      icon_ship: new Style({
        image: new Icon({
          // anchor: [0.5, 1],
          scale: 0.8,
          src: shippng,
        }),
      }),
      geoMarker: new Style({
        // image: new Circle({
        //   radius: 8,
        //   fill: new Fill({
        //     color: "blue",
        //   }),
        //   stroke: new Stroke({
        //     color: "white",
        //     width: 2,
        //   }),
        // }),
        image: new Icon({
          // anchor: [0.5, 1],
          // scale: 0.8,
          src: shippng,
        }),
      }),
    }

    this.addListener()
    this.initLayer(map)
  }

  /**
   * 创建按钮监听事件
   */
  addListener() {
    window.emitter.on("map-click", (evt) => {
      this.getSelectFeature(evt)
      this.onMap_click(evt)
    })

    window.emitter.on("popup-close", (evt) => {
      this.overlay.setPosition(undefined)
    })

    $("#sSelect").on("click", (evt) => {
      this.clickType = "start"
      this.eventFlag = true
      this.onPointSelect()
    })
    $("#eSelect").on("click", (evt) => {
      this.clickType = "end"
      this.eventFlag = true
      this.onPointSelect()
    })
    $("#doAnalysis").on("click", () => {
      this.doAnalysis_handle()
    })
    $("#clear").on("click", () => {
      this.onClear_handle()
    })
    $("#show").on("click", () => {
      this.startAnimation()
    })
  }
  /**
   * 初始化地图图层
   */
  initLayer(map) {
    this.routerLayer = new VectorLayer({
      source: new VectorSource(),
      style: (feature) => {
        return this.styles[feature.get("type")]
      },
    })
    map.addLayer(this.routerLayer)

    this.poiLayer = new VectorLayer({
      source: new VectorSource(),
    })
    this.poiLayer.layerid = "poi"
    map.addLayer(this.poiLayer)
    this.poiLayer.setZIndex(99)

    this.pointLayer = new VectorLayer({
      source: new VectorSource(),
    })
    map.addLayer(this.pointLayer)

    // 添加popup
    this.overlay = new Overlay({
      element: document.getElementById("popup"),
      autoPan: true,
      autoPanAnimation: {
        duration: 250,
      },
    })
    map.addOverlay(this.overlay)
  }

  /**
   * 获取点击选中的要素
   */
  getSelectFeature(evt) {
    const obj = this.map.forEachFeatureAtPixel(evt.pixel, (feature, layer) => {
      if (layer && layer.layerid === "poi") {
        const coordinate = evt.coordinate
        const attr = feature.getProperties()
        this.getFeatureInfo(coordinate, attr)
      }
    })
  }

  /**
   * 查询选中要素的信息并展示
   */
  getFeatureInfo(coordinate, attr) {
    let content = document.getElementById("popup-content")
    content.innerHTML = `
    <p><lable>医院等级：</lable><span>${attr.yyjbmc}</span></p>
    <p><lable>医院名称：</lable><span>${attr.hospName}</span></p>
    <p><lable>医院类型：</lable><span>${attr.speciality}</span></p>
    `

    this.overlay.setPosition(coordinate)
  }

  onMap_click(evt) {
    if (this.eventFlag == true) {
      let point = evt.coordinate
      let x = Number(point[0]).toFixed(2)
      let y = Number(point[1]).toFixed(2)
      let coor = toLonLat(evt.coordinate)
      let lon = coor[0].toFixed(6)
      let lat = coor[1].toFixed(6)
      let icon
      if (this.clickType === "start") {
        $("#sPoint").val(lon + "," + lat)
        icon = spng
      } else if (this.clickType === "end") {
        $("#ePoint").val(lon + "," + lat)
        icon = epng
      }
      this.addPointOnMap(point, icon)
    }
  }

  addPointOnMap(coor, imgurl) {
    let point = new Point(coor)
    let icon = new Style({
      image: new Icon({
        anchor: [0.5, 1],
        scale: 0.8,
        src: imgurl,
      }),
    })
    let feature = new Feature({
      geometry: point,
    })
    feature.setStyle(icon)
    if (this.clickType === "start") {
      if (this.startPoint) {
        this.pointLayer.getSource().removeFeature(this.startPoint)
      }
      this.startPoint = feature
      let point = feature.getGeometry().getCoordinates()
      this.connectLine(point)
    } else if (this.clickType === "end") {
      if (this.endPoint) {
        this.pointLayer.getSource().removeFeature(this.endPoint)
      }
      this.endPoint = feature
    }
    this.pointLayer.getSource().addFeature(feature)
  }

  onPointSelect(type) {
    if (type === "start") {
      $("#sPoint").val(1)
    } else if (type === "end") {
      $("#ePoint").val(2)
    }
  }

  connectLine(item) {
    const points = Array.from(this.islandPoints)
    points.push(item)
    const feature = this.pointLayer.getSource().getFeatures()[0]
    if (feature) {
      const geom = feature.getGeometry()
      geom.setCoordinates(points)
      this.tempCoors = points
    }
  }

  /**
   * 路径分析
   */
  doAnalysis_handle() {
    this.eventFlag = false
    var startVal = $("#sPoint").val()
    var endVal = $("#ePoint").val()
    var p1 = startVal.split(",").map(function (value) {
      return parseFloat(value)
    })
    var p2 = endVal.split(",").map(function (value) {
      return parseFloat(value)
    })
    if (startVal && endVal) {
      this.getService(p1, p2)
    } else {
      alert("请选择“起点”和“终点”")
    }
  }

  /**
   * 调用分析服务
   */
  getService(p1, p2) {
    let viewparams = [
      "x1:" + p1[0],
      "y1:" + p1[1],
      "x2:" + p2[0],
      "y2:" + p2[1],
    ]
    viewparams = viewparams.join(";")
    $.ajax({
      url: serverUrl + "pg/ows",
      type: "POST",
      dataType: "json",
      data: {
        service: "wfs",
        version: "1.0.0",
        request: "GetFeature",
        typeName: analysisServe,
        viewparams: viewparams,
        outputFormat: "application/json",
      },
    })
      .then((res) => {
        if (res) {
          this.parseResult(res)
        }
      })
      .catch((err) => {
        console.log(err)
        alert("查询分析服务失败")
      })
  }

  /**
   * 获取分析结果
   */
  parseResult(res) {
    if (res.features && res.features[0].geometry) {
      const source = this.routerLayer.getSource()
      source.clear()
      // this.removeById("landRoute")

      // 绘制分析结果路线
      let features = new GeoJSON().readFeatures(res)
      let geom = features[0].getGeometry().transform("EPSG:4326", "EPSG:3857")
      let feature = new Feature({
        type: "route",
        geometry: geom,
      })
      feature.set("id", "landRoute")

      // 轨迹动画
      let coors = [...this.tempCoors, ...geom.getCoordinates()]
      if (coors.length > 0) {
        this.position = new Point(coors[0])
        this.geoMarker = new Feature({
          type: "geoMarker",
          geometry: this.position,
        })
        const moveLine = new LineString(coors)

        source.addFeatures([feature, this.geoMarker])
        this.route = moveLine
        // this.startAnimation(moveLine)
      }
    } else {
      alert("未找到可通行路线")
    }
  }

  /**
   * 轨迹运动动画
   * @param {*} route
   */
  startAnimation() {
    this.animating = true
    this.lastTime = Date.now()
    this.routerLayer.on("postrender", this.moveFeature.bind(this, this.route))
    // hide geoMarker and trigger map render through change event
    this.geoMarker.setGeometry(null)
  }

  moveFeature(route, event) {
    const speed = 60
    const time = event.frameState.time
    const elapsedTime = time - this.lastTime
    this.distance = (this.distance + (speed * elapsedTime) / 1e6) % 2
    this.lastTime = time

    const currentCoordinate = route.getCoordinateAt(
      this.distance > 1 ? 2 - this.distance : this.distance
    )
    this.position.setCoordinates(currentCoordinate)
    const vectorContext = getVectorContext(event)
    const style = this.styles[this.jtgj] || this.styles.geoMarker
    vectorContext.setStyle(style)
    vectorContext.drawGeometry(this.position)
    // tell OpenLayers to continue the postrender animation
    map.render()
  }

  stopAnimation() {
    this.animating = false
    // Keep marker at current animation position
    this.geoMarker.setGeometry(this.position)
    this.routerLayer.un("postrender", this.moveFeature.bind(this))
  }

  /**
   * 绘制岛屿路径
   */
  draw_route(data) {
    let routeArr = data["routeArr"]
    const routeData = routeArr[0]
    let wkt = routeData["wkt"]

    let kszb = routeData["kszb"].split(" ").join(",")
    let jszb = routeData["jszb"].split(" ").join(",")
    $("#sPoint").val(kszb)
    $("#ePoint").val(jszb)

    // wkt = "LINESTRING(112.895424 9.558807,112.340231 16.829864)"
    let jtgj = routeData["jtgj"]
    if (jtgj == "1") {
      this.jtgj = "icon_plane"
    } else if (jtgj == "2") {
      this.jtgj = "icon_ship"
    } else {
      this.jtgj = "geoMarker"
    }
    // this.test()

    // 添加岛屿间的路径
    const format = new WKT()
    const routeLine = format.readFeature(wkt, {
      dataProjection: "EPSG:4326",
      featureProjection: "EPSG:3857",
    })
    let style = new Style({
      stroke: new Stroke({
        width: 4,
        color: [255, 106, 80, 0.9],
        lineDash: [20, 10],
      }),
    })
    routeLine.setStyle(style)
    this.pointLayer.getSource().addFeature(routeLine)

    // 获取岛屿路径的节点坐标
    let points = routeLine.getGeometry().getCoordinates()
    this.islandPoints = Array.from(points)

    for (let i = 0; i < points.length; i++) {
      let point = new Point(points[i])
      // let geom = point.transform("EPSG:4326", "EPSG:3857")
      let feature = new Feature({
        geometry: point,
      })
      let textStyle = new Style({
        image: new Circle({
          radius: 8,
          stroke: new Stroke({
            color: "rgba(91,180,248,0.5)",
            width: "2",
          }),
          fill: new Fill({
            color: "#67ba77",
          }),
        }),
        text: new Text({
          text: (i + 1).toString(),
          fill: new Fill({
            color: "#fff",
          }),
        }),
      })
      feature.setStyle(textStyle)
      this.pointLayer.getSource().addFeature(feature)
    }

    if ($("#sPoint").val()) {
      let coor_kszb = routeData["kszb"].split(" ").map((i) => Number(i))
      let point_kszb = fromLonLat(coor_kszb)
      this.connectLine(point_kszb)
    }
  }

  /**
   * 绘制兴趣点
   */
  draw_poi(points) {
    this.poiLayer.getSource().clear()

    for (let i = 0; i < points.length; i++) {
      let item = points[i]
      let coor = item.hospPosition.split(" ").map((n) => {
        return Number(n)
      })
      let point = new Point(coor)
      let geom = point.transform("EPSG:4326", "EPSG:3857")
      let feature = new Feature({
        geometry: geom,
      })
      feature.setProperties(item)

      let src = "./images/"
      const level = item["hospLevel"]
      if (level == "2") {
        src = h2
      } else if (level == "3") {
        src = h3
      } else {
        src = hospng
      }
      let iconStyle = new Style({
        image: new Icon({
          crossOrigin: "anonymous",
          // anchor: [0.5, 1],
          scale: 0.6,
          src: src,
        }),
      })
      feature.setStyle(iconStyle)

      this.poiLayer.getSource().addFeature(feature)
    }
  }

  /**
   * 清空事件
   */
  onClear_handle() {
    $("#sPoint").val("")
    $("#ePoint").val("")
    this.startPoint = null
    this.endPoint = null
    this.pointLayer.getSource().clear()
    this.routerLayer.getSource().clear()
    this.eventFlag = false
  }

  removeById(id) {
    const source = this.routerLayer.getSource()
    const feature = source.getFeatureById(id)
    if (feature) {
      source.removeFeature(feature)
    }
  }

  test() {
    let point = new Point(111.619911, 16.48982)
    let geom = point.transform("EPSG:4326", "EPSG:3857")
    let feature = new Feature({
      geometry: geom,
    })
    //新建图标样式
    let iconStyle = new Style({
      image: new Icon({
        name: "12",
        crossOrigin: "anonymous",
        src: shippng,
        // src: 'https://openlayers.org/en/v4.6.5/examples/data/icon.png'
      }),
    })
    //设置Icon
    feature.setStyle(iconStyle)
    this.routerLayer.getSource().addFeature(feature)
  }
}
export default Routing
